package com.wbs.shop.nuby.widget;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import android.util.AttributeSet;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tencent.smtt.export.external.interfaces.ConsoleMessage;
import com.tencent.smtt.export.external.interfaces.JsPromptResult;
import com.tencent.smtt.export.external.interfaces.JsResult;
import com.tencent.smtt.sdk.ValueCallback;
import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;
import com.wbs.shop.nuby.commom.Key;
import com.wbs.shop.nuby.jsbridge.EventInjected;
import com.wbs.shop.nuby.jsbridge.LocalInjected;
import com.wbs.shop.nuby.jsbridge.PayInjected;
import com.wbs.shop.nuby.jsbridge.SessionInjected;
import com.wbs.shop.nuby.jsbridge.UserInjected;
import com.wbs.shop.nuby.jsbridge.core.BaseInjected;
import com.wbs.shop.nuby.jsbridge.core.InjectedBean;
import com.wbs.shop.nuby.jsbridge.core.InjectedUtils;
import com.wbs.shop.nuby.utils.ImageUploadUtil;
import com.wbs.shop.nuby.utils.Logger;
import com.wbs.shop.nuby.utils.StringUtils;
import com.wbs.shop.nuby.utils.Utils;
import com.wbs.shop.nuby.view.activity.WebViewActivity;
import com.wbs.shop.nuby.view.dialog.AlertDialog;
import com.wbs.shop.nuby.view.listener.IWebView;
import com.wbs.shop.nuby.view.listener.OnSuccessListener;
import com.wbs.shop.nuby.view.listener.OnTitleChangListener;
import com.yanzhenjie.album.AlbumFile;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by zhoucl on 2018/5/21 0021.
 */
public class X5WebView extends WebView implements IWebView, ImageUploadUtil.OnUploadSuccessListener, ImageUploadUtil.OnUploadCancelListener {
    private HashMap<String, BaseInjected> injectedObjectMap = new HashMap<>();
    private ValueCallback<Uri> mUploadMsg;
    private ValueCallback<Uri[]> mFilePathCallback;
    private ImageUploadUtil mImageUploadUtil;
    protected OnTitleChangListener mOnTitleChangListener;

    @Override
    public void setOnTitleChangListener(OnTitleChangListener onTitleChangListener) {
        mOnTitleChangListener = onTitleChangListener;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

    }

    @Override
    public void onShow() {

    }

    @Override
    public void onHide() {

    }

    @Override
    public boolean onNewIntent(Intent intent) {
        return true;
    }

    public X5WebView(Context context) {
        this(context, null);
    }

    public X5WebView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        init();
    }

    private void init() {
        if (getContext() instanceof Activity) {
            mImageUploadUtil = new ImageUploadUtil((Activity) getContext());
            mImageUploadUtil.setOnUploadSuccessListener(this);
            mImageUploadUtil.setOnUploadCancelListener(this);
        }
        WebSettings webSettings = getSettings();
        webSettings.setBuiltInZoomControls(false);
        webSettings.setSupportZoom(false);
        webSettings.setDisplayZoomControls(false);
        webSettings.setJavaScriptEnabled(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        webSettings.setDefaultTextEncodingName("UTF-8");
//        webSettings.setUseWideViewPort(true);
        webSettings.setAllowFileAccess(true);
//        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webSettings.setSupportMultipleWindows(true);
        webSettings.setUserAgent(webSettings.getUserAgentString() + Key.USER_AGENT);
        if (getX5WebViewExtension() != null) {
            getX5WebViewExtension().setScrollBarFadingEnabled(false);
        }
        setHorizontalScrollBarEnabled(false);
        setVerticalScrollBarEnabled(false);
        setOverScrollMode(WebView.OVER_SCROLL_NEVER);

        String appCacheDir = getContext().getDir("cache", Context.MODE_PRIVATE).getPath();
        webSettings.setAppCachePath(appCacheDir);
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        webSettings.setDomStorageEnabled(true);
        webSettings.setDatabaseEnabled(true);
        webSettings.setAppCacheEnabled(true);
        injectedObjectMap.put(Key.JS_BRIDGE_USER, new UserInjected(this));
        injectedObjectMap.put(Key.JS_BRIDGE_EVENT, new EventInjected(this));
        injectedObjectMap.put(Key.JS_BRIDGE_PAY, new PayInjected(this));
        injectedObjectMap.put(Key.JS_SESSION, new SessionInjected(this));
        injectedObjectMap.put(Key.JS_LOCAL, new LocalInjected(this));
        setWebChromeClient(new WebChromeClient());
        setWebViewClient(new WebViewClient());
        setOnLongClickListener(v -> true);
    }

    class WebChromeClient extends com.tencent.smtt.sdk.WebChromeClient {
        @Override
        public boolean onJsAlert(WebView webView, String url, String message, JsResult jsResult) {
            new AlertDialog.Builder(getContext())
                    .setMessage(message)
                    .setNegativeButton(android.R.string.cancel, (dialog, which) -> jsResult.cancel())
                    .setPositiveButton(android.R.string.ok, (dialog, which) -> jsResult.confirm())
                    .setCancelable(false)
                    .create()
                    .show();
            return true;
        }

        @Override
        public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
            Logger.e(consoleMessage.message());
            return true;
        }

        @Override
        public boolean onJsPrompt(WebView webView, String url, String message, String s2, JsPromptResult result) {
            if (StringUtils.isNotEmpty(message)) {
                try {
                    InjectedBean injectedBean = JSON.parseObject(message, InjectedBean.class);
                    String apiName = injectedBean.getApiName();
                    int lastIndexOf = apiName.lastIndexOf(".");
                    String api = "";
                    String methodName = apiName;
                    if (lastIndexOf != -1) {
                        api = apiName.substring(0, lastIndexOf);
                        methodName = apiName.substring(lastIndexOf + 1);
                    }
                    Object injectedObject = injectedObjectMap.get(api);
                    String param = injectedBean.getParam();
                    JSONObject paramJsonObject = JSON.parseObject(param);
                    Logger.e("api==>" + api + "<==methodName==>" + methodName + "<==paramJsonObject==>" + paramJsonObject.toString());
                    Object value = InjectedUtils.invoke(X5WebView.this, injectedObject, methodName, paramJsonObject, injectedBean.getCallbacks());
                    Logger.e("value==>" + value);
                    result.confirm(value == null ? "" : value.toString());
                } catch (Exception e) {
                    Logger.e(e);
                }
            }
            return true;
        }

        // For Android 3.0+
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
            Logger.e("openFileChooser==>3+");
            mUploadMsg = uploadMsg;
            if (mImageUploadUtil != null) {
                mImageUploadUtil.selectImage();
            }
        }

        // For Android < 3.0
        public void openFileChooser(ValueCallback<Uri> uploadMsgs) {
            mUploadMsg = uploadMsgs;
            Logger.e("openFileChooser==>3-");
            if (mImageUploadUtil != null) {
                mImageUploadUtil.selectImage();
            }
        }

        // For Android  > 4.1.1
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            Logger.e("openFileChooser==>4+");
            mUploadMsg = uploadMsg;
            if (mImageUploadUtil != null) {
                mImageUploadUtil.selectImage();
            }
        }

        // For Android  >= 5.0
        public boolean onShowFileChooser(com.tencent.smtt.sdk.WebView webView,
                                         ValueCallback<Uri[]> filePathCallback,
                                         com.tencent.smtt.sdk.WebChromeClient.FileChooserParams fileChooserParams) {
            Logger.e("openFileChooser==>5+");
            mFilePathCallback = filePathCallback;
            if (mImageUploadUtil != null) {
                mImageUploadUtil.selectImage();
            }
            return true;
        }
    }

    class WebViewClient extends com.tencent.smtt.sdk.WebViewClient {
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            String title = view.getTitle();
            if (!TextUtils.isEmpty(title) && mOnTitleChangListener != null) {
                mOnTitleChangListener.onTitleChang(title);
            }
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String url) {
//            if (mOnShouldOverrideUrlLoadingListener != null &&
//                    mOnShouldOverrideUrlLoadingListener.shouldOverrideUrlLoading(HtmlActivity.this, webView, url)) {
//                return true;
//            }
            Logger.e("url==>" + url);
            if (url.startsWith("tel:")) {
                Utils.callPhone(getContext(), url);
            } else if (url.equals(getUrl())) {
                webView.loadUrl(url);
            } else {
                Bundle bundle = new Bundle();
                bundle.putString(Key.URL, url);
                try {
                    Intent intent = new Intent(getContext(), WebViewActivity.class);
                    intent.putExtras(bundle);
                    getContext().startActivity(intent);
                } catch (Exception e) {
                    Intent intent = new Intent(getContext(), WebViewActivity.class);
                    intent.putExtras(bundle);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    getContext().startActivity(intent);
                }
            }
            return true;
        }
    }

    @Override
    public void onUploadSuccess(ArrayList<AlbumFile> imageUploads) {
        if (!imageUploads.isEmpty()) {
            AlbumFile photoInfo = imageUploads.get(0);
            Uri uri = Uri.fromFile(new File(photoInfo.getPath()));
            if (null != mUploadMsg) {
                mUploadMsg.onReceiveValue(uri);
                mUploadMsg = null;
            }
            if (null != mFilePathCallback) {
                mFilePathCallback.onReceiveValue(new Uri[]{uri});
                mFilePathCallback = null;
            }
        } else {
            onCancel();
        }
    }

    @Override
    public void onCancel() {
        if (null != mUploadMsg) {
            mUploadMsg.onReceiveValue(null);
            mUploadMsg = null;
        }
        if (null != mFilePathCallback) {
            mFilePathCallback.onReceiveValue(null);
            mFilePathCallback = null;
        }
    }

    @Nullable
    @Override
    protected Parcelable onSaveInstanceState() {
        if (injectedObjectMap != null && !injectedObjectMap.isEmpty()) {
            for (Map.Entry<String, BaseInjected> entry : injectedObjectMap.entrySet()) {
                entry.getValue().onSaveInstanceState();
            }
        }
        return super.onSaveInstanceState();
    }

    @Override
    public void destroy() {
        super.destroy();
        for (Map.Entry<String, BaseInjected> entry : injectedObjectMap.entrySet()) {
            entry.getValue().onDestroy();
        }
        injectedObjectMap.clear();
    }
}
